package com.tbl.modules.wms.controller.instorage;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.tbl.common.utils.DateUtils;
import com.tbl.common.utils.PageTbl;
import com.tbl.common.utils.PageUtils;
import com.tbl.common.utils.StringUtils;
import com.tbl.modules.platform.constant.LogActionConstant;
import com.tbl.modules.platform.constant.MenuConstant;
import com.tbl.modules.platform.controller.AbstractController;
import com.tbl.modules.platform.service.system.LogService;
import com.tbl.modules.platform.service.system.RoleService;
import com.tbl.modules.platform.util.DeriveExcel;
import com.tbl.modules.wms.constant.Constant;
import com.tbl.modules.wms.constant.EmumConstant;
import com.tbl.modules.wms.entity.baseinfo.*;
import com.tbl.modules.wms.entity.instorage.InstorageDetail;
import com.tbl.modules.wms.service.baseinfo.*;
import com.tbl.modules.wms.service.instorage.InstorageDetailService;
import com.tbl.modules.wms.service.instorage.InstorageService;
import com.tbl.modules.wms.service.inventory.InventoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 入库管理--入库
 * @author 70486
 */
@Controller
@RequestMapping(value = "/storagein")
public class StorageInController extends AbstractController {

    /**
     * 入库管理-入库表
     */
    @Autowired
    private InstorageService instorageService;
    /**
     * 日志信息
     */
    @Autowired
    private LogService logService;
    /**
     * 角色信息
     */
    @Autowired
    private RoleService roleService;
    /**
     * 入库明细查询
     */
    @Autowired
    private InstorageDetailService instorageDetailService;
    /**
     * 库位信息
     */
    @Autowired
    private ShelfService shelfService;
    /**
     * 仓库
     */
    @Autowired
    private WarehouseService warehouseService;
    /**
     * 厂区信息
     */
    @Autowired
    private FactoryAreaService factoryAreaService;
    /**
     * 行车
     */
    @Autowired
    private CarService carService;
    /**
     * 盘点计划服务类
     */
    @Autowired
    private InventoryService inventoryService;
    /**
     * 盘具信息
     */
    @Autowired
    private DishService dishService;

    /**
     * 跳转到入库管理列表页面
     * @return ModelAndView
     */
    @RequestMapping(value = "/toList")
    public ModelAndView toList() {
        ModelAndView mv = this.getModelAndView();
        //okk
        mv.addObject("factoryList",inventoryService.getFactoryList(Arrays.asList(getSessionUser().getFactoryCode().split(","))));
        mv.addObject("operationCode", roleService.selectOperationByRoleId(getSessionUser().getRoleId(), MenuConstant.storagein));
        mv.setViewName("techbloom/instorage/storagein/storagein_list");
        return mv;
    }
    
    /**
     * 点击查看，跳转到详情列表页
     * @param id 标签初始化主键
     * @return ModelAndView
     */
    @RequestMapping(value = "/toInfo.do")
    @ResponseBody
    public ModelAndView toInfo(Long id) {
        ModelAndView mv = this.getModelAndView();
        mv.addObject("info", instorageDetailService.selectById(id));
        mv.setViewName("techbloom/instorage/storagein/storagein_info");
        return mv;
    }

    /**
     * 获取入库列表数据
     * @param queryJsonString 查询条件
     * @return Map<String,Object>
     */
    @RequestMapping(value = "/list.do")
    @ResponseBody
    public Map<String, Object> list(String queryJsonString) {
        Map<String, Object> map = new HashMap<>(4);
        if (!StringUtils.isEmptyString(queryJsonString)) {
            map = JSON.parseObject(queryJsonString);
        }
        //okk
        map.put("org", Arrays.asList(getSessionUser().getFactoryCode().split(",")));
        PageTbl page = this.getPage();
        PageUtils utils = instorageService.getPagePackageList(page, map);
        page.setTotalRows(utils.getTotalCount() == 0 ? 1 : utils.getTotalCount());
        //初始化分页对象
        executePageMap(map, page);
        map.put("rows", utils.getList());
        map.put("total", utils.getTotalPage() == 0 ? 1 : utils.getTotalPage());
        return map;
    }

    /**
     * 点击开始入库，初始化厂区、编码、推荐库位、行车
     * @param id 标签表货物明细主键
     * @return ModelAndView
     */
    @RequestMapping(value = "/storagestart.do")
    public ModelAndView storageStart(Long id) {
        ModelAndView mv = this.getModelAndView();
        //默认给第一个厂区  okk
        FactoryArea factoryArea = factoryAreaService.selectList(new EntityWrapper<FactoryArea>()
                .in("CODE",getSessionUser().getFactoryCode()).orderBy("CODE")).get(0);
        InstorageDetail instorageDetail = instorageService.getDetailById(id);
        //仓库列表
        List<Warehouse> warehouseList = instorageService.getWarehouseList(factoryArea.getCode());
        //okk
        List<FactoryArea> factoryAreaList=factoryAreaService.selectList(new EntityWrapper<FactoryArea>()
                .in("CODE",getSessionUser().getFactoryCode()).orderBy("CODE"));
        factoryAreaList.forEach(factoryarea-> factoryarea.setFactoryCodeName(factoryarea.getCode()+"_"+factoryarea.getName()));

        String recommendCode;
        //默认第一个厂区下的第一个仓库
        Warehouse warehouse = warehouseList.get(0);
        List<Car> carList = carService.selectList(new EntityWrapper<Car>()
                .eq("FACTORYCODE", warehouse.getFactoryCode())
                .eq("WAREHOUSECODE", warehouse.getCode()));
        Dish dish = dishService.selectOne(new EntityWrapper<Dish>().eq("CODE", instorageDetail.getDishnumber()));

        List<Shelf> recommendShelfs = shelfService.selectRecommentList(factoryArea.getCode(),warehouse.getCode(),dish.getOuterDiameter(),
                dish.getDrumType(), carList!=null&&carList.size()>0?carList.get(0).getCode():"", "",carList!=null&&carList.size()>0?
                carList.get(0).getWarehouseArea():"", instorageDetail.getSalesCode(),dish.getSuperWide(),
                "黑色".equals(instorageDetail.getColour())||StringUtils.isBlank(instorageDetail.getColour())?0:1);
        if(recommendShelfs.size()>0) {
            recommendCode = recommendShelfs.get(0).getCode();
        }else {
            //获取该仓库下未被占用的库位
            List<Shelf> shelfCodeList=shelfService.getRecommendShelf(warehouse.getCode(),warehouse.getFactoryCode(),
                    Objects.requireNonNull(carList).size()>0?carList.get(0).getWarehouseArea():"");
            recommendCode = shelfCodeList.size() > 0 ? shelfCodeList.get(0).getCode() : "";
        }

        mv.addObject("factoryList",factoryAreaList);
        mv.addObject("recommendCode",recommendCode);
        mv.addObject("instorageDetailId",id);
        mv.addObject("info", instorageDetail);
        mv.addObject("warehouseList", warehouseList);
        mv.addObject("carList", Objects.requireNonNull(carList));
        mv.setViewName("techbloom/instorage/storagein/storage_start");
        return mv;
    }

    /**
     * 手动入库，跳转到手动入库界面
     * @param id 标签表货物主键
     * @return ModelAndView
     */
    @RequestMapping(value = "/storageManual.do")
    public ModelAndView storageManual(Long id) {
        ModelAndView mv = this.getModelAndView();
        //默认给第一个厂区  okk
        FactoryArea factoryArea = factoryAreaService.selectList(new EntityWrapper<FactoryArea>()
                .in("CODE",getSessionUser().getFactoryCode()).orderBy("CODE")).get(0);
        //默认仓库  okk
        List<FactoryArea> factoryAreaList = factoryAreaService.selectList(new EntityWrapper<FactoryArea>()
                .in("CODE",getSessionUser().getFactoryCode()).orderBy("CODE"));
        factoryAreaList.forEach(factoryarea-> factoryarea.setFactoryCodeName(factoryarea.getCode()+"_"+factoryarea.getName()));

        mv.addObject("factoryList",factoryAreaList);
        mv.addObject("recommendCode","");
        mv.addObject("instorageDetailId",id);
        mv.addObject("info", instorageService.getDetailById(id));
        mv.addObject("warehouseList", instorageService.getWarehouseList(factoryArea.getCode()));
        mv.setViewName("techbloom/instorage/storagein/storage_manual_in");
        return mv;
    }

    /**
     * 仓库与行车确认-行车列表及推荐库位根据选定仓库变化
     * @param instorageDetailId 入库明细信息主键
     * @param id 仓库的主键
     * @return Map<String, Object>
     */
    @RequestMapping(value = "/warehouseChangeList.do")
    @ResponseBody
    public Map<String, Object> warehouseChangeList(Long instorageDetailId,Long id) {
        Map<String, Object> map = new HashMap<>(2);
        Warehouse warehouse = warehouseService.selectById(id);

       	map.put("list", carService.selectList(new EntityWrapper<Car>()
                .eq("FACTORYCODE", warehouse.getFactoryCode())
                .eq("STATE", Constant.INT_TWO)
                //行车列表
                .eq("WAREHOUSECODE", warehouse.getCode())));
        //推荐库位
        map.put("recommendCode", "");
        return map;
    }
    
    /**
     * 仓库与行车确认-仓库列表根据选定厂区变化
     * @param instorageDetailId 入库明细信息主键
     * @param id 厂区的主键
     * @return Map<String, Object>
     */
    @RequestMapping(value = "/factoryChangeList.do")
    @ResponseBody
    public Map<String, Object> factoryChangeList(Long instorageDetailId,Long id) {
        Map<String, Object> map = new HashMap<>(1);
        //选择的厂区
        FactoryArea factoryArea = factoryAreaService.selectById(id);

        //获取该厂区下对应的可用的仓库
       	map.put("list", warehouseService.selectList(new EntityWrapper<Warehouse>()
                .eq("FACTORYCODE", factoryArea.getCode())
                //仓库列表
                .eq("STATE", 1).orderBy("CODE")));
        return map;
    }

    /**
     * 点击开始入库的页面中的保存
     * 1.更新仓库，行车，状态信息
     * 2.判断当前状态 （1.未确认 2.已包装  3.入库中  4.入库完成）
     * @param instorageDetail 标签初始化明细
     * @return Map<String,Object>
     */
    @RequestMapping(value = "/updateWarehouseAndCar")
    @ResponseBody
    public Map<String, Object> updateWarehouseAndCar(InstorageDetail instorageDetail) {
        Map<String, Object> map = new HashMap<>(2);
        boolean result;
        String msg;
        Integer state = instorageDetailService.selectById(instorageDetail.getId()).getState();
        if (state == Constant.INT_ONE) {
            msg = "请先装包！";
            result = false;
        } else if (state == Constant.INT_FOUR) {
            msg = "入库完成,请勿重复提交！";
            result = false;
        } else if (state == Constant.INT_THREE) {
            msg = "入库中,请勿重复提交！";
            result = false;
        } else {
            msg = "提交成功！";
            result = instorageService.updateDetail(instorageDetail);
        }
        map.put("result", result);
        map.put("msg", msg);
        return map;
    }

    /**
     * 点击入库确认，跳转页面
     * @param id 入库明细主键
     * @return ModelAndView
     */
    @RequestMapping(value = "/storageconfirm.do")
    public ModelAndView storageConfirm(Long id) {
        ModelAndView mv = this.getModelAndView();
        InstorageDetail instorageDetail = instorageService.getDetailById(id);
        String recommendCode;

    	Car car = carService.selectOne(new EntityWrapper<Car>().eq("CODE", instorageDetail.getCarCode()));
    	Dish dish = dishService.selectOne(new EntityWrapper<Dish>().eq("CODE", instorageDetail.getDishnumber()));
        List<Shelf> recommendShelfs = shelfService.selectRecommentList(instorageDetail.getFactoryCode(),instorageDetail.getWarehouseCode(), dish.getOuterDiameter(),
                dish.getDrumType(),car.getCode(),"",car.getWarehouseArea(),instorageDetail.getSalesCode(), dish.getSuperWide(),
                "黑色".equals(instorageDetail.getColour())||StringUtils.isBlank(instorageDetail.getColour()) ? 0 : 1);
        if(recommendShelfs.size()>0) {
        	recommendCode = recommendShelfs.get(0).getCode();
        }else {
        	//获取未被占用的库位
            List<Shelf> shelfCodeList = shelfService.getRecommendShelf(instorageDetail.getWarehouseCode(), instorageDetail.getFactoryCode(), car.getWarehouseArea());
        	recommendCode = shelfCodeList.size() > 0 ? shelfCodeList.get(0).getCode() : "";
        }
        
        mv.addObject("info", instorageDetail);
        mv.addObject("recommendCode", recommendCode);
        mv.setViewName("techbloom/instorage/storagein/storage_confirm");
        return mv;
    }

    /**
     * 选择解除绑定库位
     * @param warehouseId 仓库主键
     * @param carId 行车主键
     * @param queryString 模糊查询条件
     * @param pageNo 页码
     * @return Map<String, Object>
     */
    @RequestMapping(value = "/selectUnbindShelf.do")
    @ResponseBody
    public Map<String, Object> selectUnbindShelf(Long warehouseId,Long carId,String queryString,int pageNo) {
        Map<String, Object> map = new HashMap<>(5);
        if (warehouseId != null) {
            map.put("warehouseId", warehouseId);
            map.put("queryString", queryString.toUpperCase());
            map.put("warehouseArea", carService.selectById(carId).getWarehouseArea());
            PageTbl page = this.getPage();
            page.setPageno(pageNo);
            PageUtils utils = instorageService.selectUnbindShelf(page, map);
            page.setTotalRows(utils.getTotalCount() == 0 ? 1 : utils.getTotalCount());
            //初始化分页对象
            executePageMap(map, page);
            map.put("result", utils.getList());
            map.put("total", utils.getTotalCount() == 0 ? 1 : utils.getTotalCount());
        }else {
            map.put("result", "");
            map.put("total", 0);
        }
        return map;
    }

    /**
     * 手动入库选择可用库位（对应厂区、仓库下）
     * @param warehouseId 仓库主键
     * @param queryString 模糊查询条件
     * @param pageSize 每页数量
     * @param pageNo 页码
     * @return Map<String, Object>
     */
    @RequestMapping(value = "/selectManualShelf.do")
    @ResponseBody
    public Map<String, Object> selectManualShelf(Long warehouseId,String queryString,int pageSize,int pageNo) {
        Map<String, Object> map = new HashMap<>(4);
        if (warehouseId != null) {
            map.put("warehouseId", warehouseId);
            map.put("queryString", queryString.toUpperCase());
            PageTbl page = this.getPage();
            page.setPageno(pageNo);
            page.setPagesize(pageSize);
            PageUtils utils = instorageService.selectManualShelf(page, map);
            page.setTotalRows(utils.getTotalCount() == 0 ? 1 : utils.getTotalCount());
            //初始化分页对象
            executePageMap(map, page);
            map.put("result", utils.getList());
            map.put("total", utils.getTotalCount() == 0 ? 1 : utils.getTotalCount());
        }else {
            map.put("result", "");
            map.put("total", 0);
        }
        return map;
    }

    /**
     * 入库确认点击入库
     * @param instoragedetailId 入库明细主键
     * @param factoryId 厂区主键
     * @param warehouseId 仓库主键
     * @param shelfId 库位主键
     * @param time 事务时间
     * @return Map<String,Object>
     */
    @RequestMapping(value = "/confirmInstorage")
    @ResponseBody
    public Map<String, Object> confirmInstorage(Long instoragedetailId,Long factoryId,Long warehouseId,Long shelfId,String time) {
        Map<String, Object> map = new HashMap<>(2);
        if (EmumConstant.instorageDetailState.STORAGED.getCode().equals(instorageDetailService.selectById(instoragedetailId).getState())) {
            map.put("result", false);
            map.put("msg", "入库完成,请勿重复提交！");
        } else {
            map = instorageService.confirmInstorage(instoragedetailId, shelfId, getSessionUser().getUserId(), time, factoryId, warehouseId);
        }

        return map;
    }


    /**
     * 导出入库登记列表Excel
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     */
    @RequestMapping(value = "/materialExcel", method = RequestMethod.POST)
    @ResponseBody
    public void materialExcel(HttpServletRequest request, HttpServletResponse response)  {
        Map<String, Object> map = new HashMap<>(12);
        if (request.getParameter("ids")!=null && !"".equals(request.getParameter("ids"))){
            map.put("idList", Arrays.stream(request.getParameter("ids").split(","))
                    .map(Long::parseLong).collect(Collectors.toList()));
        }
        map.put("qaCode", request.getParameter("queryQaCode"));
        map.put("batchno", request.getParameter("queryBatchno"));
        map.put("orderno", request.getParameter("queryDdh"));
        map.put("factoryarea", request.getParameter("queryCq"));
        map.put("mcode", request.getParameter("queryWlbh"));
        map.put("timeType", request.getParameter("queryTime"));
        map.put("startTime", request.getParameter("queryStartTime"));
        map.put("endTime", request.getParameter("queryEndTime"));
        map.put("entityNo", request.getParameter("queryEntityNo"));
        map.put("dishcode", request.getParameter("queryDishcode"));

        if (request.getParameter("queryState")!=null && !"".equals(request.getParameter("queryState"))){
            map.put("state", Arrays.stream(request.getParameter("queryState").split(","))
                    .map(Long::parseLong).collect(Collectors.toList()));
        }
        //okk
        map.put("org", Arrays.asList(getSessionUser().getFactoryCode().split(",")));
        try {
            String sheetName = "入库登记清单" + "(" + DateUtils.getDay() + ")";
            response.setHeader("Content-Type", "application/force-download");
            response.setHeader("Content-Type", "application/vnd.ms-excel");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Expires", "0");
            response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
            response.setHeader("Pragma", "public");
            response.setHeader("Content-disposition", "attachment;filename=" + new String(sheetName.getBytes("gbk"),
                    "ISO8859-1") + ".xls");

            String [] excelIndexArray = request.getParameter("queryExportExcelIndex").split(",");
            Map<String, String> mapFields = new LinkedHashMap<>();
            if (excelIndexArray.length==1&&"".equals(excelIndexArray[0])){
                mapFields.put("stateCode", "状态");
                mapFields.put("qaCode", "质保单号");
                mapFields.put("batchNo", "批次号");
                mapFields.put("ordernum", "订单号");
                mapFields.put("orderline", "订单行号");
                mapFields.put("entityNo", "工单号");
                mapFields.put("name", "组织机构");
                mapFields.put("factoryName", "厂区");
                mapFields.put("warehouseName", "仓库");
                mapFields.put("shelfCode", "库位");
                mapFields.put("materialCode", "物料编码");
                mapFields.put("materialName", "物料名称");
                mapFields.put("createtimeStr", "报验时间");
                mapFields.put("confirmTimeStr", "包装时间");
                mapFields.put("confirmName", "包装人姓名");
                mapFields.put("startStorageTimeStr", "入库扫码时间");
                mapFields.put("startstorageName", "入库扫码人");
                mapFields.put("instorageTimeStr", "入库时间");
                mapFields.put("instorageName", "入库人姓名");
                mapFields.put("meter", "数量");
                mapFields.put("unit", "单位");
                mapFields.put("weight", "重量");
                mapFields.put("colour", "颜色");
                mapFields.put("segmentno", "段号");
                mapFields.put("inspectno", "报验单号");
                mapFields.put("dishcode", "盘号");
                mapFields.put("dishnumber", "盘具编码");
                mapFields.put("model", "盘规格");
                mapFields.put("outerDiameter", "盘外径");
                mapFields.put("instorageType", "货物类型");
            }else {
                for (String s : excelIndexArray) {
                    if ("2".equals(s)) {
                        mapFields.put("stateCode", "状态");
                    } else if ("3".equals(s)) {
                        mapFields.put("qaCode", "质保单号");
                    } else if ("4".equals(s)) {
                        mapFields.put("batchNo", "批次号");
                    } else if ("5".equals(s)) {
                        mapFields.put("ordernum", "订单号");
                    } else if ("6".equals(s)) {
                        mapFields.put("orderline", "订单行号");
                    } else if ("7".equals(s)) {
                        mapFields.put("entityNo", "工单号");
                    } else if ("8".equals(s)) {
                        mapFields.put("name", "组织机构");
                    } else if ("9".equals(s)) {
                        mapFields.put("factoryName", "厂区");
                    } else if ("10".equals(s)) {
                        mapFields.put("warehouseName", "仓库");
                    } else if ("11".equals(s)) {
                        mapFields.put("shelfCode", "库位");
                    } else if ("12".equals(s)) {
                        mapFields.put("materialCode", "物料编码");
                    } else if ("13".equals(s)) {
                        mapFields.put("materialName", "物料名称");
                    } else if ("14".equals(s)) {
                        mapFields.put("createtimeStr", "报验时间");
                    } else if ("15".equals(s)) {
                        mapFields.put("confirmTimeStr", "包装时间");
                    } else if ("16".equals(s)) {
                        mapFields.put("confirmName", "包装人姓名");
                    } else if ("17".equals(s)) {
                        mapFields.put("startStorageTimeStr", "入库扫码时间");
                    } else if ("18".equals(s)) {
                        mapFields.put("startstorageName", "入库扫码人");
                    } else if ("19".equals(s)) {
                        mapFields.put("instorageTimeStr", "入库时间");
                    } else if ("20".equals(s)) {
                        mapFields.put("instorageName", "入库人姓名");
                    } else if ("21".equals(s)) {
                        mapFields.put("meter", "数量");
                    } else if ("22".equals(s)) {
                        mapFields.put("unit", "单位");
                    } else if ("23".equals(s)) {
                        mapFields.put("weight", "重量");
                    } else if ("24".equals(s)) {
                        mapFields.put("colour", "颜色");
                    } else if ("25".equals(s)) {
                        mapFields.put("segmentno", "段号");
                    } else if ("26".equals(s)) {
                        mapFields.put("inspectno", "报验单号");
                    } else if ("27".equals(s)) {
                        mapFields.put("dishcode", "盘号");
                    } else if ("28".equals(s)) {
                        mapFields.put("dishnumber", "盘具编码");
                    } else if ("29".equals(s)) {
                        mapFields.put("model", "盘规格");
                    } else if ("30".equals(s)) {
                        mapFields.put("outerDiameter", "盘外径");
                    } else if ("31".equals(s)) {
                        mapFields.put("instorageType", "货物类型");
                    }
                }
            }

            DeriveExcel.exportExcel(sheetName, instorageService.getPackageInExcelList(map), mapFields, response, "");
            logService.logInsert("包装入库管理数据导出", LogActionConstant.USER_EXPORT, request);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
